Skip to content

Route Codex smart routing over the catalog Codex loads - #1180

Draft
xsh310 wants to merge 1 commit into
databricks:mainfrom
xsh310:codex-session-catalog
Draft

xsh310 wants to merge 1 commit into
databricks:mainfrom
xsh310:codex-session-catalog

Conversation

@xsh310

@xsh310 xsh310 commented Oct 18, 2026 •

Copy link
Copy Markdown
Collaborator

Why

With smart routing on and no managed config, a routed subagent can fail because the router picks a model Codex does not have. For example, on eng-ml-inference-team-us-west-2 the router picked gpt-6-luna, Codex rejected it with Unknown model, and the session showed "The default subagent model wasn't available; retrying with a supported one."

This happens because ug and Codex build their model lists from different sources:

List Where it comes from today Example
Router menu (what ug sends to routes:select) Every system.ai model whose name looks like GPT or a known OSS family, saved by ug configure (codex_models + oss_models) 29 models
Codex's list (what /model shows and spawn_agent accepts) Codex's built in models plus /codex/v1/models, which leaves out GPT unless a model location is given 10 models

Only 10 of the 29 router options could actually be started. The other 19 (all gpt-6-* on an older Codex, older GPT versions, gpt-oss, deepseek, kimi-k3-neo) fail whenever the router picks them.

When a catalog file is configured (for example a managed model list), this does not happen: ug reads the router menu from that file and Codex loads the same file, so the two lists match.

What this PR does

Every routed Codex launch now uses one catalog file for both the router and Codex.

  1. A catalog is configured: use it, exactly as before.
  2. No catalog is configured: ug asks the gateway for the system.ai models Codex can use, by calling /codex/v1/models with the model location system.ai. With a location set, the gateway includes GPT models. ug turns the result into a catalog with prepare_codex_catalog, the same builder used for managed model lists, so GPT models keep Codex's own settings and native names. The file is passed to Codex with model_catalog_json, and the router menu is read from it.
  3. Discovery fails or returns nothing (for example codex/v1/models is not enabled for this workspace): ug prints the reason and the session starts without a catalog and without routing.
GET /codex/v1/models   (model location: system.ai)
   ├─ error or empty ─► no catalog, no routing (Codex starts as usual)
   └─ model names ─► prepare_codex_catalog ─► catalog file
                                                ├─► Codex's list
                                                └─► router menu

Because Codex does not fetch models from the gateway when a catalog file is set, both lists stay the same for the whole session.

Approaches considered

Approach Why not
Copy Codex's rule for combining its built in list with the gateway list into ug ug would drift again whenever Codex changes that rule
Ask Codex for its list at launch (codex debug models) Prints about 900 KB for 16 models, and Codex refreshes its gateway list every 5 minutes, so the router menu could still go stale during a session
One catalog file (this PR) Both sides read the same file, and it reuses the existing managed list code path

What changes for users

  • The router can only pick models that Codex can start.
  • On routed launches without a catalog, /model shows system.ai.* names, the same as users with a managed model list already see.
  • Where the gateway has not enabled /codex/v1/models yet, routed sessions start without automatic model switching instead of routing to models that may fail.
  • Each routed launch without a catalog adds one gateway call and two quick local Codex checks (under about a second in testing).

What does not change

  • Launches without smart routing.
  • Routed launches still do not apply a model provider or model location setting, as before.
  • The Codex App catalog. The new file is written per workspace under ~/.ucode and is not linked into Codex App settings.

Code changes

  • agents/codex.py: _launch_smart_routing uses the configured catalog or writes one with the new _write_smart_routing_catalog. Discovered models are sorted newest GPT first, so the starting model is still the newest GPT.
  • smart_routing/v2.py: launch_codex takes catalog_path, passes it to Codex, and builds the router menu from it. The fallback to the saved codex_models and oss_models is removed.
  • codex_config.py: custom_catalog_models() is replaced by listed_catalog_models(path).
  • agents/codex_catalog.py: prepare_codex_catalog can skip the "missing metadata" warnings. They make sense for admin chosen models, but would print on every launch for discovered ones.
  • Tests updated, plus new tests for discovery success, discovery failure, and silenced warnings. README note added.

Testing

  • Unit tests (uv run pytest): 4809 passed. tests/test_skills.py::test_orchestrator_injects_the_installed_agent_instructions also fails on main locally and was deselected.
  • ruff check, ruff format --check, and ty check pass.
  • Live check against a staging workspace with Codex 0.162.1: discovery returned 23 system.ai models (18 GPT plus glm and kimi), the starting model was gpt-6.1-sol, the router picked system.ai.gpt-6-luna, and gpt-6-luna is in the written catalog, so Codex can start it.

This pull request and its description were written by Isaac.

Without a managed config, the Codex router menu came from every cached
system.ai GPT and OSS service, while Codex could only start models in its
own catalog. Router picks such as gpt-6-luna then failed spawn_agent with
"Unknown model".

Routed launches now use one catalog file for both. A configured
model_catalog_json is used as before. Otherwise ug discovers the system.ai
models Codex can use from /codex/v1/models, builds the catalog with
prepare_codex_catalog like a managed list, and passes it to Codex. When
discovery fails, the session has no catalog and no routing.

Co-authored-by: Isaac <no-reply@databricks.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant